package com.ragdollcat.thirdaicodegenerate.ai.tool;

import cn.hutool.json.JSONObject;
import com.mybatisflex.core.query.QueryWrapper;
import com.ragdollcat.thirdaicodegenerate.constants.AppConstant;
import com.ragdollcat.thirdaicodegenerate.model.entity.App;
import com.ragdollcat.thirdaicodegenerate.model.entity.ChatHistory;
import com.ragdollcat.thirdaicodegenerate.model.entity.ProjectVersionCtl;
import com.ragdollcat.thirdaicodegenerate.service.AppService;
import com.ragdollcat.thirdaicodegenerate.service.ChatHistoryService;
import com.ragdollcat.thirdaicodegenerate.service.ProjectVersionCtlService;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolMemoryId;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * 文件修改工具
 * 支持 AI 通过工具调用的方式修改文件内容
 */
@Slf4j
@Component
public class FileModifyTool extends BaseTool {

    @Resource
    private ProjectVersionCtlService projectVersionCtlService;

    @Resource
    @Lazy
    private AppService appService;

    @Resource
    @Lazy
    private ChatHistoryService chatHistoryService;

    @Tool("修改文件内容，用新内容替换指定的旧内容")
    public String modifyFile(
            @P("文件的相对路径")
            String relativeFilePath,
            @P("要替换的旧内容")
            String oldContent,
            @P("替换后的新内容")
            String newContent,
            @ToolMemoryId String appId
    ) {
        try {
            Path path = Paths.get(relativeFilePath);
            if (!path.isAbsolute()) {
                String projectDirName = "vue_project_" + appId;
                Path projectRoot = Paths.get(AppConstant.SAVE_PATH, projectDirName);
                path = projectRoot.resolve(relativeFilePath);
            }
            if (!Files.exists(path) || !Files.isRegularFile(path)) {
                return "错误：文件不存在或不是文件 - " + relativeFilePath;
            }
            String originalContent = Files.readString(path);
            if (!originalContent.contains(oldContent)) {
                return "警告：文件中未找到要替换的内容，文件未修改 - " + relativeFilePath;
            }
            String modifiedContent = originalContent.replace(oldContent, newContent);
            if (originalContent.equals(modifiedContent)) {
                return "信息：替换后文件内容未发生变化 - " + relativeFilePath;
            }
            Files.writeString(path, modifiedContent, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
            log.info("成功修改文件: {}", path.toAbsolutePath());

            String fileName = path.getFileName().toString();
            try {
                App app = appService.getById(appId);
                Integer version = app.getVersion();


                ProjectVersionCtl ctlServiceOne = projectVersionCtlService.getOne(new QueryWrapper().eq("appId", appId).eq("fileName", fileName));

                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.eq("appId", appId);
                queryWrapper.eq("version", version + 1);
                queryWrapper.eq("messageType", "user");
                ChatHistory chatHistory = chatHistoryService.getOne(queryWrapper);
                //保存modifiedContent到vue_project版本控制表 保存具体的文件内容 版本号 + 1
                ProjectVersionCtl newProjectVersionCtl = ProjectVersionCtl.builder().
                        fileName(fileName).
                        message(chatHistory.getMessage()).
                        content(modifiedContent).
                        appId(Long.valueOf(appId)).
                        userId(app.getUserId()).
                        version(ctlServiceOne.getVersion() + 1).build();
                projectVersionCtlService.save(newProjectVersionCtl);
            } catch (Exception e) {
                log.error("文件:{},版本控制表更新版本失败！原因:", fileName, e);
            }


            return "文件修改成功: " + relativeFilePath;
        } catch (IOException e) {
            String errorMessage = "修改文件失败: " + relativeFilePath + ", 错误: " + e.getMessage();
            log.error(errorMessage, e);
            return errorMessage;
        }
    }

    /**
     * 调用工具的展示中文名称
     *
     * @return
     */
    @Override
    public String getDisplayName() {
        return "文件修改";
    }

    /**
     * 得到工具的英文名称
     *
     * @return
     */
    @Override
    public String getName() {
        return "modifyFile";
    }

    /**
     * 工具调用的结果
     *
     * @param jsonObject
     * @return
     */
    @Override
    public String callToolResult(JSONObject jsonObject) {
        String relativeFilePath = jsonObject.getStr("relativeFilePath");
        String oldContent = jsonObject.getStr("oldContent");
        String newContent = jsonObject.getStr("newContent");
        return String.format("""
                [工具调用] 修改文件 %s
                
                替换前：
                ```
                %s
                ```
                
                替换后：
                ```
                %s
                ```
                """, relativeFilePath, oldContent, newContent);
    }
}
